/**
 * 
 */
package jacek.kowalczyk.internal.time;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.Format;
import java.util.Calendar;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

/**
 * @author kowalczy jacek.kowalczyk@teleatlas.com
 */
public class TimeTracker extends JFrame {

    public final long workDay = 8 * 60 * 60 * 1000 + 30 * 60 * 1000;
    public long leftTime;
    private final JTextArea informationTextField;
    private boolean exit = false;
    private String leftTimeLabelText;
    private final JButton pauseResumeButton;
    private final JButton dumpButton;
    private boolean pause = false;
    private MouseListener trackerContextMenu;
    private final JLabel statusLabel;
    private final Font textFont;
    private long elapsedTime;
    private final JLabel elapsedTimeLabel;
    private Date targetDate;

    /**
     * @return the targetDate
     */
    public Date getTargetDate() {
        return targetDate;
    }

    /**
     * @param targetDate the targetDate to set
     */
    public void setTargetDate(final Date targetDate) {
        this.targetDate = targetDate;
    }

    private String dumpFilePath = "timetracker.dmp";
    private final Date startDate;
    private final JButton loadButton;
    private final JLabel statusIcon;
    private Color textColor;

    /**
     * @return the leftTime
     */
    public long getLeftTime() {
        return leftTime;
    }

    /**
     * @param leftTime the leftTime to set
     */
    public synchronized void setLeftTime(final long leftTime) {
        this.leftTime = leftTime;
    }

    /**
     * @return the elapsedTime
     */
    public long getElapsedTime() {
        return elapsedTime;
    }

    /**
     * @param elapsedTime the elapsedTime to set
     */
    public synchronized void setElapsedTime(final long elapsedTime) {
        this.elapsedTime = elapsedTime;
    }

    public TimeTracker() throws HeadlessException {
        super();
        informationTextField = new JTextArea("");
        informationTextField.setEditable(false);
        informationTextField.setLineWrap(true);
        informationTextField.setRows(5);
        exit = false;
        leftTimeLabelText = "";
        leftTime = workDay;
        pauseResumeButton = new JButton("   Pause/Resume");
        pauseResumeButton.setIcon(getImageIcon("Pause-Normal-icon.png"));
        dumpButton = new JButton("Dump state");
        loadButton = new JButton("Load state");
        statusLabel = new JLabel("Status: Time is ticking");
        // this.statusIcon = new JLabel(new Icon() {
        //
        // int width;
        // int height;
        // public void paintIcon(Component c, Graphics g, int x, int y) {
        // InputStream is = TimeTracker.class.getClassLoader().getResourceAsStream("ajax-loader.gif");
        // BufferedImage image;
        // try {
        // image = ImageIO.read(is);
        // g.drawImage(image, x, y, c);
        // width = image.getWidth();
        // height = image.getHeight();
        // } catch (IOException e) {
        // e.printStackTrace();
        // }
        //
        //
        // }
        //
        // public int getIconWidth() {
        // return width;
        // }
        //
        // public int getIconHeight() {
        // return height;
        // }
        // });
        // ImageIcon icon = null;
        // java.net.URL imgURL = TimeTracker.class.getClassLoader().getResource("ajax-loader.gif");
        // if (imgURL != null) {
        // icon = new ImageIcon(imgURL, "Time is ticking");
        // }
        statusIcon = new JLabel(getImageIcon("ajax-loader.gif"));
        textFont = new Font("Tahoma-Plain-18", Font.BOLD, 18); // NOI18N
        elapsedTime = 0L;
        elapsedTimeLabel = new JLabel("Elapsed time:\n");

        targetDate = new Date();
        final Date now = new Date();

        targetDate.setTime(now.getTime() + workDay);
        startDate = new Date();
        textColor = Color.RED;
    }

    private ImageIcon getImageIcon(final String fileName) {
        ImageIcon icon = null;
        final java.net.URL imgURL = TimeTracker.class.getClassLoader().getResource(fileName);
        if (imgURL != null) {
            icon = new ImageIcon(imgURL, "Time is ticking");
        }
        return icon;

    }

    class BackgroundThread implements Runnable {

        // private Date targetDate;
        // private String leftTimeLabelText = "dd days hh hours mm minutes";
        // private boolean exit = false;
        private int progresCounter = 0;

        public void run() {
            String progres = "";
            final String progresText0 = "background thread remaining time ";
            System.out.println(progresText0);
            // try {
            // System.out.println(progresText0);
            // } catch (IOException e1) {
            // // TODO Auto-generated catch block
            // e1.printStackTrace();
            // }
            while (!exit) {
                try {

                    // if (getLeftTime() <= 0) {
                    // leftTimeLabelText = "I is time to go home !!! :-)";
                    // } else {

                    leftTimeLabelText = "Remaining time:\n " + getHoursMinutesText(getLeftTime());

                    final String progresText1 = " " + leftTime + " = " + getHoursMinutesText(getLeftTime()) + "        ";
                    final String progresText2 = "background thread " + leftTimeLabelText;
                    //

                    try {
                        // System.out.println(progresText +"\r".getBytes("UTF-8"));
                        // System.out.print("remaining time " + leftTime );
                        System.out.write((byte)'\r');
                        System.out.write(progresText1.getBytes());
                        // System.out.write(getHoursMinutesText(leftTime).getBytes());
                        // System.out.write(13);

                    } catch (final IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    informationTextField.setText(leftTimeLabelText);
                    informationTextField.setFont(textFont); // NOI18N
                    informationTextField.setForeground(textColor);
                    informationTextField.repaint();

                    elapsedTimeLabel.setText("Elapsed time:\n " + getHoursMinutesText(elapsedTime));
                    elapsedTimeLabel.repaint();
                    // jCheckBox1.repaint();
                    if (isPause()) {
                        final Date now = new Date();
                        final long milisecondsNow = now.getTime();
                        targetDate.setTime(milisecondsNow + getLeftTime());

                    } else {

                        final Date now = new Date();
                        final long milisecondsNow = now.getTime();
                        setLeftTime(targetDate.getTime() - milisecondsNow);
                        if (getLeftTime() <= 0) {
                            textColor = Color.GREEN;
                        }
                        setElapsedTime(milisecondsNow - startDate.getTime());

                        if (progresCounter == 10) {
                            progres = "";
                            progresCounter = 0;
                        }
                        // else if (progresCounter % 1000 == 0){
                        // progres = progres + ".";
                        // }
                        else {
                            progres = progres + ".";
                        }
                        progresCounter++;
                        statusLabel.setText("Status: Time is ticking " + progres);
                        statusLabel.repaint();
                    }
                    // }///else

                    // Thread.sleep(60000);//1 minute
                    Thread.sleep(1000);// 1 mili second
                } catch (final InterruptedException ex) {
                    ex.printStackTrace();
                }
            }

        }
    }

    /**
     * @param args
     */
    public static void main(final String[] args) {
        // TODO Auto-generated method stub
        final TimeTracker tt = new TimeTracker();
        final File f = new File(tt.dumpFilePath);
        if (f.exists()) {
            f.delete();
        }
        if (args.length >= 1) {
            tt.setLeftTime(tt.initTime(args[0]));
            tt.getTargetDate().setTime(new Date().getTime() + tt.getLeftTime());
        }

        tt.initComponents();
        tt.initBackground();

        tt.setVisible(true);
    }

    protected void setPause(final boolean b) {
        pause = b;

    }

    protected boolean isPause() {
        return pause;
    }

    public static String getHoursMinutesText(final long milisecTime) {
        final long hours = milisecTime / (1000 * 60 * 60);
        final long lastHourTime = milisecTime % (1000 * 60 * 60);
        final long minutes = lastHourTime / (1000 * 60);
        return " " + hours + " hours " + minutes + " minutes";

    }

    public static long getMilisecTime(final int hours, final int minutes, final int seconds) {
        long time = 0L;
        time += seconds * 1000;
        time += minutes * 60 * 1000;
        time += hours * 60 * 60 * 1000;
        return time;
    }

    public static long getHours(final long milisecTime) {
        final long hours = milisecTime / (1000 * 60 * 60);
        // long lastHourTime = milisecTime % (1000 * 60 * 60);
        // long minutes = lastHourTime / (1000 * 60);
        return hours;
    }

    public static long getMinutes(final long milisecTime) {
        final long hours = milisecTime / (1000 * 60 * 60);
        final long lastHourTime = milisecTime % (1000 * 60 * 60);
        final long minutes = lastHourTime / (1000 * 60);
        return minutes;
    }

    public static long getMiliSeconds(final long hours, final long minutes) {
        final long milisecunds = hours * 60 * 60 * 1000 + minutes * 60 * 1000;
        return milisecunds;
    }

    private void initComponents() {
        final Dimension d = new Dimension(200, 240);

        setSize(d);
        setMaximumSize(d);
        setMinimumSize(d);
        setLocationRelativeTo(null);
        setResizable(false);
        setTitle("TimeTracker");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        final GridBagLayout gbl = new GridBagLayout();
        setLayout(gbl);
        final GridBagConstraints gbc = new GridBagConstraints();

        pauseResumeButton.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                if (isPause()) {
                    setPause(false);
                    pauseResumeButton.setText("            Pause");
                    pauseResumeButton.setIcon(getImageIcon("Pause-Normal-icon.png"));
                    statusLabel.setText("Status: Time is ticking");
                    // statusIcon = new JLabel(getProgressIcon("ajax-loader.gif"));
                    statusIcon.setIcon(getImageIcon("ajax-loader.gif"));
                    repaint();
                } else {
                    setPause(true);
                    pauseResumeButton.setText("          Resume");
                    pauseResumeButton.setIcon(getImageIcon("Play-Normal-icon.png"));
                    statusLabel.setText("Status: Paused");
                    statusIcon.setIcon(getImageIcon("Pause-Disabled-icon.png"));
                    repaint();
                }
            };
        });

        dumpButton.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                // Date now = new Date();
                // setDumpFilePath(dumpFilePath+"_"+now.getTime());
                saveRemainingTime(dumpFilePath);
            };
        });

        loadButton.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                loadRemainingTime(dumpFilePath);
            };
        });

        trackerContextMenu = new MouseListener() {

            public void mouseReleased(final MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mousePressed(final MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mouseExited(final MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mouseEntered(final MouseEvent e) {
                // TODO Auto-generated method stub

            }

            public void mouseClicked(final MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    showInitDialog();
                }

            }
        };
        informationTextField.addMouseListener(trackerContextMenu);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        getContentPane().add(informationTextField, gbc);

        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 2;

        getContentPane().add(elapsedTimeLabel, gbc);

        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 2;
        getContentPane().add(pauseResumeButton, gbc);

        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.weightx = 0.5;
        gbc.gridwidth = 1;
        getContentPane().add(dumpButton, gbc);

        gbc.fill = GridBagConstraints.NONE;
        gbc.gridx = 1;
        gbc.gridy = 3;
        gbc.weightx = 0.5;
        gbc.gridwidth = 1;
        getContentPane().add(loadButton, gbc);

        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.weightx = 1.0;
        gbc.gridwidth = 2;
        getContentPane().add(statusLabel, gbc);

        // statusIcon
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.weightx = 1.0;
        gbc.gridwidth = 2;
        getContentPane().add(statusIcon, gbc);

    }

    protected void showInitDialog() {
        final JDialog initDialog = new JDialog(this);
        final Dimension d = new Dimension(200, 150);

        initDialog.setSize(d);
        initDialog.setMaximumSize(d);
        initDialog.setMinimumSize(d);
        initDialog.setLocationRelativeTo(null);
        initDialog.setResizable(false);
        initDialog.setTitle("init TimeTracker");
        initDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        initDialog.setLayout(new GridLayout(5, 1));
        final JTextField initField = new JTextField("" + leftTime);
        final JTextField initHoursField = new JTextField("" + getHours(getLeftTime()));
        final JLabel initHoursLabel = new JLabel("hours");
        final JTextField initMinutesField = new JTextField("" + getMinutes(getLeftTime()));
        final JLabel initMinutesLabel = new JLabel("minutes");
        final JButton initButton = new JButton("Set time ");
        initButton.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent e) {
                final long temp = getLeftTime();
                try {
                    // long time = initTime(initField.getText());
                    final long h = initTime(initHoursField.getText());
                    final long m = initTime(initMinutesField.getText());
                    final long time = getMiliSeconds(h, m);
                    setLeftTime(time);

                } catch (final NumberFormatException ex) {
                    ex.printStackTrace();
                    setLeftTime(temp);

                } finally {
                    final Date now = new Date();
                    targetDate.setTime(now.getTime() + getLeftTime());

                    if (leftTime <= 0) {
                        leftTimeLabelText = "I is time to go home !!! :-)";
                    } else {
                        leftTimeLabelText = "Remaining time:\n " + getHoursMinutesText(getLeftTime());
                        System.out.println(leftTimeLabelText);
                        System.out.println("remaining time set from dialog " + leftTime + " ="
                            + getHoursMinutesText(leftTime));
                        System.out.println("background thread remaining time ");
                        informationTextField.setText(leftTimeLabelText);
                        informationTextField.setFont(textFont); // NOI18N
                        informationTextField.repaint();
                        initDialog.dispose();
                    }
                }

            }
        });
        initDialog.add(initHoursField);
        initDialog.add(initHoursLabel);
        initDialog.add(initMinutesField);
        initDialog.add(initMinutesLabel);

        // initDialog.add(initField);
        initDialog.add(initButton);
        initDialog.setVisible(true);
    }

    private void initBackground() {
        final BackgroundThread job = new BackgroundThread();
        final Thread worker = new Thread(job);
        worker.start();

    }

    private long initTime() {

        return workDay;
    }

    private long initTime(final String remainingTime) {
        return Long.parseLong(remainingTime);

    }

    private String loadRemainingTime(final String filePath) {
        final String timeValue = "";
        File in;
        FileReader fr;
        BufferedReader br;
        try {
            in = new File(filePath);
            fr = new FileReader(in);
            br = new BufferedReader(fr);
            String s = null;

            try {
                s = br.readLine();
                if (s != null && s.length() > 0) {
                    setLeftTime(Long.parseLong(s));
                    JOptionPane.showMessageDialog(this,
                        "The remaining time was loaded from the dump file " + in.getCanonicalPath(), "Time loaded",
                        JOptionPane.INFORMATION_MESSAGE);
                }
            } catch (final IOException e) {
                e.printStackTrace();
            }

        } catch (final FileNotFoundException e) {
            e.printStackTrace();
        }
        return timeValue;
    }

    private boolean saveRemainingTime(final String filePath) {
        File out;
        FileWriter fw;
        BufferedWriter bw;

        try {
            out = new File(filePath);
            fw = new FileWriter(out);
            bw = new BufferedWriter(fw);

            bw.write("" + getLeftTime());
            bw.close();
            JOptionPane.showMessageDialog(this, "The remaining time was saved to the dump file " + out.getCanonicalPath(),
                "File saved", JOptionPane.INFORMATION_MESSAGE);
            return true;

        } catch (final FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } catch (final IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }

    }

    /**
     * @return the dumpFilePath
     */
    public String getDumpFilePath() {
        return dumpFilePath;
    }

    /**
     * @param dumpFilePath the dumpFilePath to set
     */
    public void setDumpFilePath(final String dumpFilePath) {
        this.dumpFilePath = dumpFilePath;
    }

}
